/*
 * author: Mladen Krstic (mladen.krstic@tfzr.rs)
 * © 2010 All rights reserved
 */

package com.mladen;


import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import com.google.api.javame.*;
import java.util.Enumeration;
import java.io.*;

import java.util.Hashtable;


/**
 * @author Mladen
 */
public class gTranslation extends MIDlet implements CommandListener, Runnable {

    private boolean midletPaused = false;
    private boolean isPimSupported = true;
    private static boolean canceledRequest = false;
    private Hashtable langs;
    private SMSSender sender = null;
    private String port = "5000";
    private String translated;
    private String resultTitle;
    
    //<editor-fold defaultstate="collapsed" desc=" Generated Fields ">
    private Command exitCommand;
    private Command okCommand;
    private Command exitCommand2;
    private Command sendCommand;
    private Command cancelCommand;
    private Command sendSmsCommand;
    private Command exitSmsCommand;
    private Command closeAboutCommand;
    private Form form;
    private Form sendForm;
    private Form waitingForm;
    private ChoiceGroup from;
    private ChoiceGroup to;
    private TextField text;
    private TextField smsnumber;
    private TextField smstext;
    private Gauge gauge;
    private TextBox resultBox;
    
    private StringItem stringItem;
    private Image image3;
    private Image image2;
    private Image image1;
    private Image image;
    private Image image7;
    private Image image6;
    private Image image5;
    private Image image4;
    private Image image8;
    
    //</editor-fold>

    //</editor-fold>

    /**
     * The HelloMIDlet constructor.
     */
    public gTranslation() {
    }

    public static synchronized boolean isCanceledRequest() {
        return canceledRequest;
    }
    public static synchronized void setCanceledRequest(boolean b) {
        canceledRequest = b;
    }
    public void run() {
        String fromLang = (String) langs.get(from.getString(from.getSelectedIndex()));
        String toLang = (String) langs.get(to.getString(to.getSelectedIndex()));
        String txt = text.getString().trim();
        if (fromLang.equals(toLang) || txt.equals("")) {
            Alert at = new Alert("", "Insert text, please", null, AlertType.INFO);
            switchDisplayable(at, form);
            return;
        }
        try {
            translated = Translate.getUnicode(Translate.translate(txt, fromLang, toLang).getBytes());
            if (fromLang.equals(Language.AUTO_DETECT)) {
                fromLang = Translate.AUTO_DETECTED_LANGUAGE;
                resultTitle = fromLang + " (detected) " + "-" + toLang;
            } else {
                resultTitle = fromLang + " - " + toLang;
            }
        } catch (Exception ex) {
            Alert at = new Alert("Error", "Error occured. Check your GPRS settings and try again", null, AlertType.ERROR);
            getDisplay().setCurrent(at, getForm());
        }
        if (resultBox != null) {
            resultBox.setString(translated);
            resultBox.setTitle(resultTitle);
        }
        if (!isCanceledRequest())
            switchDisplayable(null, getResultBox());
        setCanceledRequest(false);
            
    }

    //<editor-fold defaultstate="collapsed" desc=" Generated Methods ">
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: initialize ">
    /**
     * Initilizes the application.
     * It is called only once when the MIDlet is started. The method is called before the <code>startMIDlet</code> method.
     */
    private void initialize() {
        // write pre-initialize user code here
        langs = new Hashtable();
        langs.put("Auto-detect", Language.AUTO_DETECT);
        langs.put("Croatian", Language.CROATIAN);
        langs.put("English", Language.ENGLISH);
        langs.put("French", Language.FRENCH);
        langs.put("German", Language.GERMAN);
        langs.put("Italian", Language.ITALIAN);
        langs.put("Russian", Language.RUSSIAN);
        langs.put("Serbian", Language.SERBIAN);
        langs.put("Slovenian", Language.SLOVENIAN);
        langs.put("Spanish", Language.SPANISH);
        sender = SMSSender.getInstance();
        try {
            verifyPIMSupport();

        } catch (Exception ex) {
            isPimSupported = false;
        }

        // write post-initialize user code here
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: startMIDlet ">
    /**
     * Performs an action assigned to the Mobile Device - MIDlet Started point.
     */
    public void startMIDlet() {
        // write pre-action user code here
        switchDisplayable(null, getForm());
        // write post-action user code here
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: resumeMIDlet ">
    /**
     * Performs an action assigned to the Mobile Device - MIDlet Resumed point.
     */
    public void resumeMIDlet() {
        // write pre-action user code here

        // write post-action user code here
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: switchDisplayable ">
    /**
     * Switches a current displayable in a display. The <code>display</code> instance is taken from <code>getDisplay</code> method. This method is used by all actions in the design for switching displayable.
     * @param alert the Alert which is temporarily set to the display; if <code>null</code>, then <code>nextDisplayable</code> is set immediately
     * @param nextDisplayable the Displayable to be set
     */
    public void switchDisplayable(Alert alert, Displayable nextDisplayable) {
        // write pre-switch user code here
        Display display = getDisplay();
        if (alert == null) {
            display.setCurrent(nextDisplayable);
        } else {
            display.setCurrent(alert, nextDisplayable);
        }
        // write post-switch user code here
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Method: commandAction for Displayables ">
    /**
     * Called by a system to indicated that a command has been invoked on a particular displayable.
     * @param command the Command that was invoked
     * @param displayable the Displayable where the command was invoked
     */
    public void commandAction(Command command, Displayable displayable) {
        // write pre-action user code here
        if (displayable == form) {
            if (command == exitCommand) {
                // write pre-action user code here
                exitMIDlet();
                // write post-action user code here
            } else if (command == okCommand) {
                // write pre-action user code here
                if (text.getString().trim().equals("")) {
                    Alert at = new Alert("Alert", "Insert text, please", null, AlertType.INFO);
                    getDisplay().setCurrent(at);
                } else if (from.getString(from.getSelectedIndex()).equals(to.getString(to.getSelectedIndex()))) {
                    translated = text.getString();
                    if (resultBox != null)
                        resultBox.setString(translated);
                    switchDisplayable(null, getResultBox());
                } else {
                    (new Thread(this)).start();
                    switchDisplayable(null, getWaitingForm());
                }
                // write post-action user code here
            } else if (command == aboutCommand) {
                switchDisplayable(null, getAboutForm());
            } else if (command == playFrom) {
                String text2speech = text.getString().trim();
                if (text2speech.length() > 0) {
                    (new AudioPlayer(text2speech, (String)langs.get(from.getString(from.getSelectedIndex())), this, getForm())).start();
                    switchDisplayable(null, getWaitingForm());
                } else {
                    Alert at = new Alert("Warning", "No text given.", null, AlertType.WARNING);
                    getDisplay().setCurrent(at);
                }
            }
        } else if (displayable == resultBox) {
            if (command == exitCommand2) {
                // write pre-action user code here
                switchDisplayable(null, getForm());
                // write post-action user code here
            } else if (command == sendCommand) {
                    getDisplay().setCurrent(getSendForm());
            } else if (command == play) {
                String text2speech = resultBox.getString().trim();
                if (text2speech.length() > 0) {
                    (new AudioPlayer(text2speech, (String)langs.get(to.getString(to.getSelectedIndex())), this, getResultBox())).start();
                    switchDisplayable(null, getWaitingForm());
                } else {
                    Alert at = new Alert("Warning", "No text given.", null, AlertType.WARNING);
                    getDisplay().setCurrent(at);
                }
            }
        } else if (displayable == waitingForm) {
            if (command == cancelCommand) {
                setCanceledRequest(true);
                if (AudioPlayer.isRunning) {
                    switchDisplayable(null, getResultBox());
                } else {
                    switchDisplayable(null, getForm());
                }
                
            }
        } else if (displayable == sendForm) {
            if (command == sendSmsCommand) {
                String dest = smsnumber.getString().trim();
                String msg = smstext.getString();
                if (dest.length() > 0) {
                    sender.sendMsg(dest, port, msg);
                } else {
                    Alert at = new Alert("Warning", "Insert number, please.", null, AlertType.INFO);
                    getDisplay().setCurrent(at);
                }
            } else if (command == exitSmsCommand) {
                if (!sender.isSending())
                    switchDisplayable(null, getResultBox());
            } 
        } else if (displayable == aboutForm) {
            if (command == closeAboutCommand) {
                System.out.println("Pritisnut close");
                switchDisplayable(null, getForm());
            }
        }
        // write post-action user code here
    }
    
    //</editor-fold>    
    public void verifyPIMSupport() throws IOException {
        String version = "";
        version = System.getProperty("microedition.pim.version");
        if (version != null) {
          if (!version.equals("1.0"))
            throw new IOException("Package is not version 1.0.");
        }
        else
          throw new IOException("PIM optional package is not available.");
  }

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: exitCommand ">
    /**
     * Returns an initiliazed instance of exitCommand component.
     * @return the initialized component instance
     */
    public Command getExitCommand() {
        if (exitCommand == null) {
            // write pre-init user code here
            exitCommand = new Command("Exit", Command.EXIT, 0);
            // write post-init user code here
        }
        return exitCommand;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: form ">
    /**
     * Returns an initiliazed instance of form component.
     * @return the initialized component instance
     */
    private Form aboutForm;

    public Form getAboutForm() {
        if (aboutForm == null) {
            aboutForm = new Form("About gTranslation");
            form.append("\n");
            ImageItem image = new ImageItem("", getGoogleImage(), Item.LAYOUT_CENTER | ImageItem.LAYOUT_NEWLINE_BEFORE | ImageItem.LAYOUT_NEWLINE_AFTER, "");
            aboutForm.append(image);
            StringItem thanks = new StringItem("","Thank you for use gTranslation");
            thanks.setLayout(Item.LAYOUT_CENTER | ImageItem.LAYOUT_NEWLINE_AFTER);
            aboutForm.append(thanks);
            StringItem feedback = new StringItem("Send us your feedback & suggestions on:", "mladen.krstic@tfzr.rs", StringItem.HYPERLINK);
            feedback.setLayout(Item.LAYOUT_CENTER);
            aboutForm.append(feedback);
            aboutForm.addCommand(getCloseAboutCommand());
            aboutForm.setCommandListener(this);

        }
        return aboutForm;
    }

    public Command getCloseAboutCommand() {
        if (closeAboutCommand == null) {
            closeAboutCommand = new Command("Back", Command.BACK, 0);
        }
        return closeAboutCommand;
    }
    public Form getForm() {
        if (form == null) {
            // write pre-init user code here
            form = new Form("gTranslation", new Item[] { getText(), getFrom(), getTo() });
            form.addCommand(getExitCommand());
            form.addCommand(getOkCommand());
            form.addCommand(getPlayFromCommand());
            form.addCommand(getAboutCommand());
            form.setCommandListener(this);
            // write post-init user code here
        }
        return form;
    }
    private Command aboutCommand;
    public Command getAboutCommand() {
        if (aboutCommand == null) {
            aboutCommand = new Command("About", Command.HELP, 2);
        }
        return aboutCommand;
    }
    //</editor-fold>
    public Form getSendForm() {
        if (sendForm == null) {            
            sendForm = new Form("");
            sendForm.append(getSmsNumber());
            sendForm.append(getSmsText());
            sendForm.addCommand(getExitSmsCommand());
            sendForm.addCommand(getSendSmsCommand());
            sendForm.setCommandListener(this);
        } else {
            smsnumber.setString("");
            smstext.setString(getSmsTextStr());
        }
        return sendForm;
    }
    public Command getSendSmsCommand() {
        if (sendSmsCommand == null) {
            // write pre-init user code here
            sendSmsCommand = new Command("Send", Command.SCREEN, 1);
            // writesendSmsCommand post-init user code here
        }
        return sendSmsCommand;
    }

    public Command getExitSmsCommand() {
        if (exitSmsCommand == null) {
            // write pre-init user code here
            exitSmsCommand = new Command("Back", Command.BACK, 0);
            // writesendSmsCommand post-init user code here
        }
        return exitSmsCommand;
    }
    private TextField getSmsNumber() {
        if (smsnumber == null) {
            // write pre-init user code here
            smsnumber = new TextField("Phone number:", "", 20, TextField.PHONENUMBER);
            smsnumber.setPreferredSize(-1, -1);
            // write post-init user code here
            
        }
        return smsnumber;
    }
    private String getSmsTextStr() {
        String txt = resultBox.getString();
        if (txt.length() > 160) {
            txt = txt.substring(0, 159);
        }
        return txt;
    }
    private TextField getSmsText() {
        String txt = resultBox.getString();
        if (txt.length() > 160) {
            txt = txt.substring(0, 159);
        }
        if (smstext == null) {
            smstext = new TextField("Message:", txt, 160, TextField.ANY);
            smstext.setPreferredSize(-1, 100);
        } else {
            smstext.setString(txt);
        }
        return smstext;
    }
    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: text ">
    /**
     * Returns an initiliazed instance of text component.
     * @return the initialized component instance
     */
    public TextField getText() {
        if (text == null) {
            // write pre-init user code here
            text = new TextField("Text:", null, 500, TextField.ANY);
            text.setPreferredSize(-1, -1);
            // write post-init user code here
        }
        return text;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: from ">
    /**
     * Returns an initiliazed instance of from component.
     * @return the initialized component instance
     */
    public ChoiceGroup getFrom() {
        if (from == null) {
            // write pre-init user code here
            from = new ChoiceGroup("From:", Choice.POPUP);
            Enumeration en = langs.keys();
            from.append("Auto-detect", null);
            from.append("Croatian", getImage());
            from.append("English", getImage1());
            from.append("French", getImage2());
            from.append("German", getImage3());
            from.append("Italian", getImage4());
            from.append("Russian", getImage5());
            from.append("Serbian", getImage6());
            from.append("Slovenian", getImage7());
            from.append("Spanish", getImage8());
            from.setFitPolicy(Choice.TEXT_WRAP_DEFAULT);
            from.setSelectedFlags(new boolean[] { true, false, false, false, false, false, false, false, false, false });
            // write post-init user code here
        }
        return from;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: okCommand ">
    /**
     * Returns an initiliazed instance of okCommand component.
     * @return the initialized component instance
     */
    public Command getOkCommand() {
        if (okCommand == null) {
            // write pre-init user code here
            okCommand = new Command("Translate", Command.SCREEN, 1);
            // write post-init user code here
        }
        return okCommand;
    }
    //</editor-fold>
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: to ">
    /**
     * Returns an initiliazed instance of to component.
     * @return the initialized component instance
     */
    public ChoiceGroup getTo() {
        if (to == null) {
            // write pre-init user code here
            to = new ChoiceGroup("To:", Choice.POPUP);
                       to.append("Croatian", getImage());
            to.append("English", getImage1());
            to.append("French", getImage2());
            to.append("German", getImage3());
            to.append("Italian", getImage4());
            to.append("Russian", getImage5());
            to.append("Serbian", getImage6());
            to.append("Slovenian", getImage7());
            to.append("Spanish", getImage8());
            to.setFitPolicy(Choice.TEXT_WRAP_DEFAULT);
            to.setSelectedFlags(new boolean[] { false, true, false, false, false, false, false, false, false });

        }
        return to;
    }
    //</editor-fold>



    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image ">
    /**
     * Returns an initiliazed instance of image component.
     * @return the initialized component instance
     */
    public Image getImage() {
        if (image == null) {
            // write pre-init user code here
            try {
                image = Image.createImage("/croatia.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image1 ">
    /**
     * Returns an initiliazed instance of image1 component.
     * @return the initialized component instance
     */
    public Image getImage1() {
        if (image1 == null) {
            // write pre-init user code here
            try {
                image1 = Image.createImage("/unitedkingdom.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image1;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image2 ">
    /**
     * Returns an initiliazed instance of image2 component.
     * @return the initialized component instance
     */
    public Image getImage2() {
        if (image2 == null) {
            // write pre-init user code here
            try {
                image2 = Image.createImage("/france.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image2;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image3 ">
    /**
     * Returns an initiliazed instance of image3 component.
     * @return the initialized component instance
     */
    public Image getImage3() {
        if (image3 == null) {
            // write pre-init user code here
            try {
                image3 = Image.createImage("/germany.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image3;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image4 ">
    /**
     * Returns an initiliazed instance of image4 component.
     * @return the initialized component instance
     */
    public Image getImage4() {
        if (image4 == null) {
            // write pre-init user code here
            try {
                image4 = Image.createImage("/italy.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image4;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image5 ">
    /**
     * Returns an initiliazed instance of image5 component.
     * @return the initialized component instance
     */
    public Image getImage5() {
        if (image5 == null) {
            // write pre-init user code here
            try {
                image5 = Image.createImage("/russia.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image5;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image6 ">
    /**
     * Returns an initiliazed instance of image6 component.
     * @return the initialized component instance
     */
    public Image getImage6() {
        if (image6 == null) {
            // write pre-init user code here
            try {
                image6 = Image.createImage("/serbia.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image6;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image7 ">
    /**
     * Returns an initiliazed instance of image7 component.
     * @return the initialized component instance
     */
    public Image getImage7() {
        if (image7 == null) {
            // write pre-init user code here
            try {
                image7 = Image.createImage("/slovenia.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image7;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: image8 ">
    /**
     * Returns an initiliazed instance of image8 component.
     * @return the initialized component instance
     */
    public Image getImage8() {
        if (image8 == null) {
            // write pre-init user code here
            try {
                image8 = Image.createImage("/spain.gif");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
            // write post-init user code here
        }
        return image8;
    }
    //</editor-fold>

    
    private Image googleImage;
    public Image getGoogleImage() {
        if (googleImage == null) {
            try {
               googleImage = Image.createImage("/google.png");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
        }
       return googleImage;
    }












    //</editor-fold>







    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: exitCommand2 ">
    /**
     * Returns an initiliazed instance of exitCommand2 component.
     * @return the initialized component instance
     */
    public Command getExitCommand2() {
        if (exitCommand2 == null) {
            // write pre-init user code here
            exitCommand2 = new Command("Back", Command.EXIT, 0);
            // write post-init user code here
        }
        return exitCommand2;
    }
    //</editor-fold>
    public Command getSendCommand() {
        if (sendCommand == null) {
            sendCommand = new Command("Send", Command.SCREEN, 2);
        }
        return sendCommand;
    }
    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: resultBox ">
    /**
     * Returns an initiliazed instance of resultBox component.
     * @return the initialized component instance
     */
    public TextBox getResultBox() {
        if (resultBox == null) {
            // write pre-init user code here
            resultBox = new TextBox(resultTitle, translated, 500, TextField.ANY | TextField.UNEDITABLE);
            resultBox.addCommand(getExitCommand2());
            resultBox.addCommand(getSendCommand());
            resultBox.addCommand(getPlayCommand());
            resultBox.setCommandListener(this);
            // write post-init user code here

        }
        return resultBox;
    }
    //</editor-fold>
    private Command playFrom;
    public Command getPlayFromCommand() {
        if (playFrom == null) {
            playFrom = new Command("Speak!", Command.SCREEN, 1);
        }
        return playFrom;
    }
    private Command play;
    public Command getPlayCommand() {
        if (play == null) {
            play = new Command("Speak!", Command.SCREEN, 1);
        }
        return play;
    }






    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: stringItem ">
    /**
     * Returns an initiliazed instance of stringItem component.
     * @return the initialized component instance
     */
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: cancelCommand ">
    /**
     * Returns an initiliazed instance of cancelCommand component.
     * @return the initialized component instance
     */
    
    public Command getCancelCommand() {
        if (cancelCommand == null) {
            // write pre-init user code here
            cancelCommand = new Command("Cancel", Command.CANCEL, 0);
            // write post-init user code here
        }
        return cancelCommand;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc=" Generated Getter: waitingForm ">
    /**
     * Returns an initiliazed instance of waitingForm component.
     * @return the initialized component instance
     */
    public Form getWaitingForm() {
        if (waitingForm == null) {
            // write pre-init user code here
            waitingForm = new Form("", new Item[] { new Spacer(0, 20), getGauge() });
            waitingForm.addCommand(getCancelCommand());
            waitingForm.setCommandListener(this);
            
            // write post-init user code here
        }
        return waitingForm;
    }
    
    public Gauge getGauge() {
        if (gauge == null) {
            gauge = new Gauge("Processing your request", false, Gauge.INDEFINITE, Gauge.CONTINUOUS_RUNNING);
        }
        return gauge;
    }
    //</editor-fold>





    /**
     * Returns a display instance.
     * @return the display instance.
     */
    public Display getDisplay () {
        return Display.getDisplay(this);
    }

    /**
     * Exits MIDlet.
     */
    public void exitMIDlet() {
        switchDisplayable (null, null);
        destroyApp(true);
        notifyDestroyed();
    }

    /**
     * Called when MIDlet is started.
     * Checks whether the MIDlet have been already started and initialize/starts or resumes the MIDlet.
     */
    public void startApp() {
        if (midletPaused) {
            resumeMIDlet ();
        } else {
            initialize ();
            startMIDlet ();
        }
        midletPaused = false;
    }

    /**
     * Called when MIDlet is paused.
     */
    public void pauseApp() {
        midletPaused = true;
    }

    /**
     * Called to signal the MIDlet to terminate.
     * @param unconditional if true, then the MIDlet has to be unconditionally terminated and all resources has to be released.
     */
    public void destroyApp(boolean unconditional) {
    }

    
}
